home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
asmutil
/
asm_n_z.zip
/
SIT.ASM
< prev
next >
Wrap
Assembly Source File
|
1989-10-23
|
18KB
|
652 lines
;SIT -- enhanced SET for MS-DOS
;
;source code and executable placed IN THE PUBLIC DOMAIN by the author:
;
; Davidson Corry
; 4610 SW Lander
; Seattle, WA 98116
; (206) 935-0244
;
;support and enhancements are NOT guaranteed in any way, but
; if you have a question, suggestion, or comment, call me up.
; I might be tickled enough to do something about it!
;
;
;Written for Microsoft MASM 5.1
;
;Use the following commands to create SIT.COM:
;
; MASM SIT;
; LINK SIT; (ignore the warning about NO STACK)
; EXE2BIN SIT
; REN SIT.BIN SIT.COM
;
;and then you can erase SIT.OBJ and SIT.EXE
;
;
include sit.inc ;structured ASM macros, etc.
;operation codes
report equ 1
create equ 2
remove equ 3
append equ 4
prepend equ 5
cseg segment byte public
assume cs:cseg, ds:cseg, ss:cseg, es:nothing
; CS = DS = ES = SS = PSP segment in .COM format programs
org 100h ;.COM format executable
;; ============= Primary routine
main:
call locate_master_environment
call clean_up_command_line
_if <cmp byte ptr ds:[80h],0>,ne ;there ARE command line arguments
xor cx,cx
mov cl,ds:[80h]
inc cx ;copy command line INCLUDING terminating null
mov ax,cs
mov es,ax
mov si,81h
mov di,offset line_buffer
cld
rep movsb
xor ax,ax
stosb ;terminate with a null
call process_line
_else ;there are NO command line arguments, read lines from Standard Input
_while <call read_from_stdin>,nc ;UNsuccessful read of a line from STDIN
call process_line
_wend
_endif
mov ax,4c00h ;terminate program
dos
;; ============== coded data
public master_env_seg, master_env_siz
master_env_seg dw 0 ;segment address of master environment copy
master_env_siz dw 0 ;size (in bytes) of master environment copy
public variable_size, variable_posn
variable_size dw 0 ;size (in bytes) of resultant VARIABLE=VALUE string
variable_posn dw 0 ;position (in master environment area) to replace new VARIABLE=VALUE string
public variable_name_size
variable_name_size dw 0
public operation
operation db 0 ;which op to perform? remove, change, append, prepend, report?
public no_room_msg
no_room_msg db 'Master environment allocation exceeded$'
public bad_syntax_msg
bad_syntax_msg db 'Bad syntax. Usage is VARIABLE { [ | = | += | -= | &= ] VALUE STRING }$'
public cant_find_command_com_msg
cant_find_command_com_msg db 'Cannot locate primary command shell, terminating.$'
public cant_find_master_env_msg
cant_find_master_env_msg db 'Cannot locate master environment segment, terminating.',cr,lf
db ' If you are using 4DOS, you must use the /M:nnn switch -- see 4DOS.DOC$'
;; ============== support routines
public clean_up_command_line
clean_up_command_line:
xor cx,cx
mov cl,ds:[80h] ;CX = size of command line passed to SIT
xor dx,dx ;clear bitflags 01 = "there were nonblank characters"
mov si,81h
_if ,ncxz ;if there are some chars on command line...
_loop
_if <cmp byte ptr [si],' '>,a
or dx,01 ;there are nonblank characters in the command line
_endif
inc si
_nextcx
_endif
_if <test dx,1>,z ;there were NO non-blank characters in command line, kill command line
mov byte ptr ds:[80h],0 ;pretend the command line was empty
_endif
mov si,81h
xor bx,bx
mov bl,ds:[80h]
mov byte ptr [bx+si],0 ;null-terminate command line
ret
public read_from_stdin
read_from_stdin:
mov dx,offset line_buffer
_loop
mov ah,3fh ;"read from file handle"
mov bx,0 ;STDIN file handle, always open
mov cx,1 ;get 1 character
dos
_break <test ax,ax>,z ;no characters read, we're at end-of-file
mov si,dx
_break <cmp byte ptr [si],'Z'-'@'>,e ;ctrl-Z is end-of-file too!
;Input from STDIN may have lines delimited by
; CR alone, LF alone, CR/LF or LF/CR (depending on
; whether the source is the keyboard or a text file
; from any of several kinds of editors.
;To handle the re-display consistently, we
; 1) treat CR and LF identically
; 2) treat CR (or LF) as an end-of-line marker
; ONLY when there are characters in the line buffer,
; otherwise ignore it.
; 3) echo all characters up to EOL, then explicitly send
; a CR/LF
_if <cmp byte ptr [si],lf>,e ;treat LF = CR
mov byte ptr [si],cr
_endif
_if <cmp byte ptr [si],cr>,e ;possible end-of-line
_again <cmp dx,offset line_buffer>,e ;no chars in buffer, ignore CR
mov byte ptr [si],0 ;terminate line with null
_break
_endif
inc dx
_lend
;read from STDIN reached end-of-file or end-of-line, return CARRY if buffer is empty
_if <cmp dx,offset line_buffer>,e ;no chars
stc ;set CARRY = unsuccessful read
_else
clc
_endif
ret
public locate_master_environment
locate_master_environment:
;locate master copy of environment
;first step is to locate the master copy of COMMAND.COM
; (or whatever command shell is in charge)
;This is the first memory block that "owns itself" --
; that is, the segment of the arena header is one less than
; the segment of the PSP that owns it
;see Ray Duncan's ADVANCED MS-DOS for an excellent discussion
; of memory allocation and arena headers in MS-DOS
;NOTE *** in version 1.0 of SIT, I assumed that the segment portion of
; the INT 2Eh vector pointed to the master COMMAND.COM segment --
; that turned out to be true for Microsoft COMMAND.COM, but
; not for the (excellent) shareware replacement 4DOS --
; The following method is more robust, and correctly finds both
; COMMAND.COM and 4DOS.
mov ah,52h
dos ;undocumented DOS call, returns ES:BX -> "list of lists"
mov ax,es:-2[bx] ;BX is the segment address of the first DOS memory allocation block
push ax ;save the pointer to the first memory block
_loop
mov es,ax ;ES -> segaddr of arena header
inc ax ;AX -> segaddr of memory block itself
cmp ax,es:[1] ;see if they're the same
_if ,e ;yes, they're the same, AX is the segaddr of the primary shell COMMAND.COM
mov di,ax ;save it in AX for next loop
_break
_endif
_if <cmp byte ptr es:[0],'Z'>,e ;reached end of arena header chain, COMMAND.COM not found (impossible, but true...)
mov dx,offset cant_find_command_com_msg
mov ah,9
dos
mov ax,4cffh ;quit with errorlevel 255
dos
_endif
add ax,es:[3] ;advance AX -> next arena header
_lend
pop ax ;restore segment address of first memory block
_loop
mov es,ax ;ES segment is a memory allocation block ("arena header")
;see who "owns" this block of memory -- the PSP segment
; of the owner is the value in the word at ES:[1]
_if <cmp di,es:[1]>,e ;master COMMAND.COM owns it, see if it's the master environment
_if <cmp word ptr es:[3],3>,a ;3-paragraph block is the CURRENTLY-RUNNING PROGRAM block
inc ax ;AX is segment address of memory block ITSELF (rather than its arena header)
cmp di,ax ;compare to COMMAND.COM PSP segment value
mov ax,es ;restore AX -> arena header, but doesn't affect flags from CMP DI,BX
;The first three memory blocks owned by the master copy of COMMAND.COM are usually
; 1) COMMAND.COM itself,
; 2) a 48-byte block containing the name of the
; currently-executing program, and
; 3) the master environment block
;
;We can tell them apart because the arena header for COMMAND.COM will be
; immediately preceding the memory block for COMMAND.COM (segment pointed by DI),
; while the arena header for the master environment strings block will
; be somewhere else.
_if ,ne ;arena header did NOT immediately precede the DI segment, we've found master environment block
inc ax ;AX -> segment of environment block
mov master_env_seg,ax
mov ax,es:[3] ;size of memory block in paragraphs
shl ax,1
shl ax,1
shl ax,1
shl ax,1 ;AX = size of memory block in BYTES
mov master_env_siz,ax
mov ax,cs
mov es,ax ;restore ES = local segment
ret ;done, return to main routine